<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
    <link href="https://cdn.bootcdn.net/ajax/libs/normalize/7.0.0/normalize.min.css" rel="stylesheet">
</head>
<body>
<h2>单例模式</h2>
<h3>1. 定义</h3>
<p>保证一个类仅有一个实例，并提供一个访问它的全局访问点</p>

<h3>2. 核心</h3>
<p>确保只有一个实例，并提供全局访问</p>

<script type="text/javascript">
//3. 实现 
//假设要设置一个管理员，多次调用也仅设置一次，我们可以使用闭包缓存一个内部变量来实现这个单例

function SetManager(name) {
    this.manager = name;
}
SetManager.prototype.getName = function () {
    console.log(this.manager)
    return this.manager
}

var SingletonSetManager = (function () {
    var manager = null;

    return function (name) {
        if (!manager) {
            manager = new SetManager(name);
        }

        return manager
    }
})();

SingletonSetManager('jam').getName();
//这是比较简单的做法，但是假如我们还要设置一个HR呢？就得复制一遍代码了
//所以，可以改写单例内部，实现地更通用一些

//==================================================
// 提取出通用的单例
function getSingleton(fn) {
    var instance = null;
    return function() {
        console.log(arguments)
        if (!instance) {
            instance = fn.apply(this, arguments);
        }

        return instance;
    }
}
var managerSingleton = getSingleton(function (name) {
    var manager = new SetManager(name);
    return manager;
})
managerSingleton('jam').getName()

//==================================================
//这时，我们添加HR时，就不需要更改获取单例内部的实现了，仅需要实现添加HR所需要做的，再调用即可
function SetHr(name) {
    this.hr = name;
}

SetHr.prototype.getName = function() {
    console.log(this.hr);
};

var hrSingleton = getSingleton(function(name) {
    var hr = new SetHr(name);
    return hr;
});

hrSingleton('thisHr').getName();

//==========================================================
//或者，仅想要创建一个div层，不需要将对象实例化，直接调用函数
//结果为页面中仅有第一个创建的div
function createPopup(htmlCont) {
    var div = document.createElement('div')
    div.innerHTML = htmlCont;
    div.style.display = 'none';
    document.body.append(div)
    return div
}

var popupSingleton = getSingleton(function() {
    var pop = createPopup.apply(this, arguments);
    pop.style.display = 'block';
    return pop
});

console.log(
    popupSingleton('createPopup111').innerHTML,     //打印得出：createPopup111
    popupSingleton('createPopup222').innerHTML,     //打印得出：createPopup111
    popupSingleton('createPopup333').innerHTML      //打印得出：createPopup111
);


/*
function CreateDiv(html) {
    this.html = html;
    this.init();
}
CreateDiv.prototype.init = function(){
    var div = document.createElement("div");
    div.innerHTML = this.html;
    document.body.appendChild(div);
};

var popupSingleton = getSingleton(function(html) {
    return new CreateDiv(html);
});
//popupSingleton('CreateDiv传参内容')

console.log(popupSingleton('CreateDiv传参内容').innerHTML)
*/

</script>
</body>
</html>